package org.deltaset.meta.internal;

import java.lang.reflect.Method;
import java.util.List;
import org.deltaset.meta.Finder;
import org.deltaset.meta.annotation.DsFirstResult;
import org.deltaset.meta.annotation.DsMaxResult;

/**
 *
 * @author dmakariev
 */
class PagedFinder implements Finder {

    private final Method counter;
    private final Method finder;
    private final Object service;

    PagedFinder(final Method counter, final Method finder, final Object service) {
        this.counter = counter;
        this.finder = finder;
        this.service = service;
    }

    @Override
    public long counter(final Object... params) {
        if (null == this.counter) {
            return -1;
        }
        final Long count = (Long) ReflectionUtils.execute(counter, service, params);
        return count;
    }

    @Override
    public List<Object> finder(final int firstResult, final int maxResult, final Object... params) {
        //some conventions; the DsFirstResult and DsMaxResult could be only on first or second place
        //(or if there is an context object they could be on second and third place); not supporting member and context finder for now.
        //this check should (also) go to the MetaActionType.mapMethod        
        final int indexFirstResult = ReflectionUtils.indexOf(finder, DsFirstResult.class);
        final int indexMaxResult = ReflectionUtils.indexOf(finder, DsMaxResult.class);

        if (-1 == indexFirstResult || -1 == indexMaxResult) {
            final String firstResultNotFound = (-1 == indexFirstResult) ? "@" + DsFirstResult.class.getName() : "";
            final String maxResultNotFound = (-1 == indexMaxResult) ? "@" + DsMaxResult.class.getName() : "";
            throw new RuntimeException("ERROR " + finder.getDeclaringClass() + "." + finder.getName() + " does NOT have parameters annotated with : " + firstResultNotFound + " " + maxResultNotFound);
        }

        if (indexFirstResult == indexMaxResult
                || indexFirstResult > 1
                || indexMaxResult > 1) {
            throw new RuntimeException("ERROR " + finder.getDeclaringClass() + "." + finder.getName() + " has wrong indexes for indexFirstResult=" + indexFirstResult + " and/or indexMaxResult=" + indexMaxResult);
        }

        final int allParamsSize = (null != params) ? params.length + 2 : 2;
        final Object[] allParams = new Object[allParamsSize];
        allParams[indexFirstResult] = firstResult;
        allParams[indexMaxResult] = maxResult;
        System.arraycopy(params, 0, allParams, 2, params.length);

        return (List<Object>) ReflectionUtils.execute(finder, service, allParams);
    }
}
